/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
//package berkeley.project1;

/* DList.java */

/**
 *  A DList1 is a mutable doubly-linked list.  (No sentinel, not
 *  circularly linked.)
 */

public class DList {

  /**
   *  head references the first node.
   *  tail references the last node.
   *
   *  DO NOT CHANGE THE FOLLOWING FIELD DECLARATIONS.
   */

  protected DListNode head;
  protected DListNode tail;
  public long size;

  /* DList1 invariants:
   *  1)  head.prev == null.
   *  2)  tail.next == null.
   *  3)  For any DListNode1 x in a DList, if x.next == y and x.next != null,
   *      then y.prev == x.
   *  4)  For any DListNode1 x in a DList, if x.prev == y and x.prev != null,
   *      then y.next == x.
   *  5)  The tail can be accessed from the head by a sequence of "next"
   *      references.
   *  6)  size is the number of DListNode1s that can be accessed from the
   *      head by a sequence of "next" references.
   */

  /**
   *  DList1() constructor for an empty DList1.
   */
  public DList() {
    head = null;
    tail = null;
    size = 0;
  }

  /**
   *  DList1() constructor for a one-node DList1.
   */
  public DList(int[] a) {
    head = new DListNode();
    tail = head;
    head.item = a;
    size = 1;
  }

  /**
   *  DList1() constructor for a two-node DList1.
   */
  public DList(int[] a, int[] b) {
    head = new DListNode();
    head.item = a;
    tail = new DListNode();
    tail.item = b;
    head.next = tail;
    tail.prev = head;
    size = 2;
  }

  /**
   *  insertFront() inserts an item at the front of a DList1.
   */
  public void insertFront(int[] i) {
    if (head == null) {
        head = tail = new DListNode(i);
    } else {
        DListNode temp = head;
        head = new DListNode(i);
        temp.prev = head;
        
        head.next = temp;
        head.prev = null;
    }
    size++;
  }

  /**
   *  removeFront() removes the first item (and node) from a DList1.  If the
   *  list is empty, do nothing.
   */
  public void removeFront() {
      if (head != null) {
        if (head.next == null) {
            head = tail = null;
        } else {
            head = head.next;
            head.prev = null;
        }
        size--;
      }
  }
  
  public void insertEnd(int[] i) {
    if (head == null) {
        head = tail = new DListNode(i);
    } else {
        DListNode temp = new DListNode(i);
        temp.next = null;
        temp.prev = tail;
        tail.next = temp;
        tail = temp;
    }
    size++;
  }
  
  public void removeCurrentNode(DListNode node) {
      DListNode prevNode = node.prev;
      DListNode nextNode = node.next;
      if (prevNode != null) {
          prevNode.next = nextNode;
      }
      if (nextNode != null) {
          nextNode.prev = prevNode;
      }
      size--;
  }
  
  public void insertAfter(DListNode node, DListNode newNode) {
      DListNode temp = node.next;
      if (temp == null) {
          insertEnd(newNode.getItem());
      } else {
        node.next = newNode;
        newNode.prev = node;
        newNode.next = temp;
        temp.prev = newNode;
        size++;
      }
  }
  
  public void insertBefore(DListNode node, DListNode newNode) {
      DListNode temp = node.prev;
      if (temp == null) {
          insertFront(newNode.getItem());
      } else {
        node.prev = newNode;
        newNode.next = node;
        newNode.prev = temp;
        temp.next = newNode;
        size++;
      }
  }
  
    public DListNode nth(int position) {
    DListNode currentNode;

    if ((position < 0) || (head == null)) {
      return null;
    } else {
      currentNode = head;
      while (position > 0) {
        currentNode = currentNode.next;
        if (currentNode == null) {
          return null;
        }
        position--;
      }
      return currentNode;
    }
  } 

  /**
   *  toString() returns a String representation of this DList.
   *
   *  DO NOT CHANGE THIS METHOD.
   *
   *  @return a String representation of this DList.
   */
  public String toString() {
    String result = "[  ";
    DListNode current = head;
    while (current != null) {
      result = result + current.item + "  ";
      current = current.next;
    }
    return result + "]";
  }

}
